Form validation is an important part of any app.
In this article, we’ll look at how to use Vee-Validate 4 in our Vue 3 app for form validation.
Call Set Form Validation Methods from Form’s ref
We can access the setFieldError
and setErrors
methods from the Form
component’s ref.
For example, we can write:
<template>
<Form @submit="onSubmit" ref="myForm">
<Field name="email" as="input" />
<ErrorMessage name="email" />
<br />
<Field name="password" as="input" />
<ErrorMessage name="password" />
<br />
<input type="submit" />
</Form>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
components: {
Form,
Field,
ErrorMessage,
},
data() {
const schema = yup.object().shape({
email: yup.string().required().email(),
name: yup.string().required(),
password: yup.string().required().min(8),
});
return {
schema,
};
},
methods: {
onSubmit(values) {
this.$refs.myForm.setFieldError("email", "this email is already taken");
this.$refs.myForm.setErrors({
email: "this field is already taken",
password: "someone already has this password",
});
},
},
};
</script>
We call setFieldError
and setErrors
from the form’s ref.
Validating Nested Objects
We can validate nested form objects with the Field
component.
For example, we can write:
<template>
<Form @submit="onSubmit" :validation-schema="schema">
<Field name="links.twitter" type="url" />
<ErrorMessage name="links.twitter" />
<br />
<Field name="links.github" type="url" />
<ErrorMessage name="links.github" />
<br />
<button>Submit</button>
</Form>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
components: {
Form,
Field,
ErrorMessage,
},
data() {
const schema = yup.object().shape({
links: yup.object().shape({
twitter: yup.string().url(),
github: yup.string().url(),
}),
});
return {
schema,
};
},
methods: {
onSubmit(values) {
alert(JSON.stringify(values, null, 2));
},
},
};
</script>
We set the name
attribute to the path to the field we want to validate in the Field
and ErrorMessage
components.
In the schema
object, we do the same thing.
We call yup.object().shape()
and add the links
property inside the object we pass in as the argument.
Validating Nested Arrays
We can also use Vee-Validate 4 to validate nested arrays.
For instance, we can write:
<template>
<Form @submit="onSubmit" :validation-schema="schema">
<Field name="links[0]" type="url" />
<ErrorMessage name="links[0]" />
<br />
<Field name="links[1]" type="url" />
<ErrorMessage name="links[1]" />
<br />
<button>Submit</button>
</Form>
</template>
<script>
import { Form, Field, ErrorMessage } from "vee-validate";
import * as yup from "yup";
export default {
components: {
Form,
Field,
ErrorMessage,
},
data() {
const schema = yup.object().shape({
links: yup.array().of(yup.string().url()),
});
return {
schema,
};
},
methods: {
onSubmit(values) {
alert(JSON.stringify(values, null, 2));
},
},
};
</script>
to add the array validation.
We can check if an array of strings is a URL by writing:
yup.array().of(yup.string().url())
Composition API
We can add validation to our Vue 3 components if we use the composition API.
To do this, we write:
<template>
<Form @submit="onSubmit" v-slot="{ errors }" :validation-schema="schema">
<Field name="user.name" as="input" />
<span id="nameErr">{{ errors["user.name"] }}</span>
<br />
<Field name="user.addresses[0]" as="input" id="address" />
<span id="addrErr">{{ errors["user.addresses[0]"] }}</span>
<br />
<button id="submit">Submit</button>
</Form>
</template>
<script>
import { Form, Field } from "vee-validate";
import * as yup from "yup";
export default {
components: {
Form,
Field,
},
setup() {
return {
schema: yup.object({
user: yup.object({
name: yup.string().required(),
addresses: yup.array().of(yup.string().required()),
}),
}),
onSubmit(values) {
console.log(values);
},
};
},
};
</script>
The setUp
method returns the schema
reactive property and the onSubmit
method.
Conclusion
We can validate forms with the composition API and validate objects and nested arrays.